from PyQt4.QtGui import * 
from PyQt4.QtCore import * 
import struct

class Pixel:
    def __init__(self, x, y, color, image = None):
        self.x = x
        self.y = y
        self.color = color
        self.image = image
        self.width = image.rect().width()
        self.height = image.rect().height()

    def hsv_offset(image, h, s, v):
        for y in range(image.height()):
            for x in range(image.width()):
                color = QColor(image.pixel(x, y))
                oh, os, ov, oa = color.getHsv()
                oh += h
                os += s
                ov += v
                # Boundaries
                if oh < 0:
                    oh = 0
                if oh > 359:
                    oh = 359 
                if os < 0:
                    os = 0
                if os > 255:
                    os = 255
                if ov < 0:
                    ov = 0
                if ov > 255:
                    ov = 255
                # Set it
                color.setHsv(oh, os, ov)
                image.setPixel(x,y,color.rgb())
        return image

    hsv_offset = staticmethod(hsv_offset)
    
    def flood_fill(image, x, y, target_color, replacement_color):
        try:
            pixel = Pixel.getPixel(image, x, y)

            if pixel:
                if x >= 0 and x < pixel.width and y >= 0 and y < pixel.height and pixel.color == target_color and pixel.color != replacement_color:
                    image.setPixel(x, y, replacement_color.rgb())
                    """
                    p = QPainter(image)
                    p.setPen(QPen(replacement_color))
                    p.drawPoint(x, y)
                    p.end()
                    """
                    
                    Pixel.flood_fill(image, x + 1, y, target_color, replacement_color)
                    Pixel.flood_fill(image, x - 1, y, target_color, replacement_color)
                    Pixel.flood_fill(image, x, y + 1, target_color, replacement_color)
                    Pixel.flood_fill(image, x, y - 1, target_color, replacement_color)
        except Exception, ex:
            print "FloodFill: %s (%d, %d)" % (ex, x, y)
            
    flood_fill = staticmethod(flood_fill)
            
    def getPixel(image, x, y):
        if x >= 0 and x < image.rect().width() and y >= 0 and y < image.rect().height():
            """
            line = image.scanLine(y).asstring(image.bytesPerLine())
            offset = x*4
            try:
                rgba = struct.unpack_from('BBBB', line, offset)
            except Exception, ex:
                print "%s (%d, %d) offset: %d bytes_per_line: %d total_bytes: %d" % (ex, x, y, offset, range(image.bytesPerLine() / 4), image.numBytes())
            color = QColor(rgba[2],rgba[1],rgba[0],rgba[3])
            """
            color = QColor(image.pixel(x,y))
            pixel = Pixel(x, y, color, image)
            return pixel
        else:
            return None
    
    getPixel = staticmethod(getPixel)
    
    def QImageToPixels(image):
        pixels = []
        bytes = image.bits().asstring(image.numBytes())
        total_lines = image.numBytes() / image.bytesPerLine()
        for y in range(total_lines):
            for x in range(image.bytesPerLine() / 4):
                offset = y*image.bytesPerLine() + x*4
                try:
                    rgba = struct.unpack_from("BBBB", bytes, offset)
                except Exception, ex:
                    print "%s (%d, %d) offset: %d bytes_per_line: %d total_bytes: %d" % (ex, x, y, offset, range(image.bytesPerLine() / 4), image.numBytes())
                color = QColor(rgba[2],rgba[1],rgba[0],rgba[3])
                pixel = Pixel(x, y, color, image)
                pixels.append(pixel)
        return pixels

    QImageToPixels = staticmethod(QImageToPixels)
